Blog Application with React Native
In this tutorial, we will be creating a blog mobile application where you will be able to write your personal blogs and diaries. These blogs will be created and stored locally on your device. You may recall that previously we used static data to populate the application. However, we will now learn how to store text data on local devices. This is made possible with Expo’s AsyncStorage.
For this tutorial, we will be creating a two page application. The first page will be where we show a concise preview of all of the blogs we have created and the next page will be where we can create, edit and delete our blogs.
Watch the video below to have an idea of what you will be building.
Helpful prior knowledge
As stated on the module page
Learning Outcomes
By the end of this tutorial, you will be able to:
- Apply the map() function to iterate through an array
- Learn how to use AsyncStorage to store data locally
- Use the same components for various purposes like create and edit
- Fetch data from AsyncStorage and populate the data on the screen
Tutorial Steps
Total steps: 11
-
Step 1: Project Setup
In this step, we will be setting up our environment to develop our blog application. Firstly, open any code editor of your choice. Choose any folder as your project root folder and open up your terminal.
Enter the following commands in your computer’s terminal.
npx expo init blog-app cd blog-app npm install @react-navigation/native @react-navigation/native-stack npx expo install react-native-screens react-native-safe-area-context npm install @expo/vector-icons npm i @react-native-async-storage/async-storage npx expo startThis code sets up a new React Native project, blog-app using the Expo CLI tool. The first line initializes a new project using the expo init command, while the second line changes the current working directory to the newly created project.
The next set of commands installs several packages that are necessary for the project to run, including packages for navigation using
@react-navigation/nativeand@react-navigation/native-stack. These packages are installed using thenpm installcommand. Additionally, thenpx expo installcommand is used to install other necessary dependencies, such as react-native-screens and react-native-safe-area-context.Finally, the npm install command is used to install
@expo/vector-icons, a package that provides icons for use in the application. The last package we need is the@react-native-async-storage/async-storagepackage. This package will allow us to store local data onto our mobile application. Usually you may choose to store session token and other crucial information that can identify your users. You may also notice that we also used npm i instead of npm install. This is a shorthand for installing packages. You may use either when installing new packages for any JavaScript projects.The last line,
npx expo start, starts the Expo development server and launches the application in the emulator or on a connected device. -
Step 2: File and Folder Management
Once we are done with downloading the dependencies, we will create some files and folders. First, in the blog-app folder, create a new folder called pages. In the pages folder, create two new files, IndexPage.js and BlogPage.js. These are the files we will be working with to display the two pages.
As you may realise, Expo has installed and created the node_modules folder which contains all of the dependencies we need for this React Native project. The assets folder will be where you will be able to add in your own images. Any time when you may want to use any images from the assets folder, you should make the image path you are referencing relative to this folder.
Lastly, App.js will be the entry file that React Native will first interact with.
You may check your folder structure against the image below.
-
Step 3: Content Page and View Management
We will now set up our content page for this application. Previously, we used the App.js file to keep track of all of the files and pages that will be displayed on our application.
Replace all the template code in App.js with the code below.
We have imported the dependencies that we installed in Step 1. These dependencies from React Navigation will be used to control what the user is seeing on their screen. We will be using the Stack Navigation.
Replace the code within the return() statement of the App function with the code snippet as shown below.
To check if you correctly edited the code in App.js, you may refer to the image below.
Let's understand our code now. The
<NavigationContainer>component is the top-level component provided by the React Navigation library that manages the navigation state for your entire app.Within the <NavigationContainer> component in line 9, a
<Stack.Navigator>component is used to wrap the screens that will be managed by the Stack Navigation type. The <Stack.Navigator> component is responsible for controlling the stack-based navigation of your application.The
<Stack.Screen>component in line 11 is used to define a single screen within the stack-based navigation. Each <Stack.Screen> component must have a uniquenameprop, which is used to refer to that specific screen within the stack, and acomponentprop, the React component that will be rendered for that screen.In this example, there is only one <Stack.Screen> component defined, with a name of "Index" and a component of
IndexPage. This means that when the navigation stack is at this screen, the IndexPage component will be rendered.Each time we would like to create a new page, each page needs to have their own <Stack.Screen> element. The two crucial props we will need to add in are the name and the component prop. In any project, each page should have a unique name. There should not be any screens with the same name prop. We can also use the
optionprop to adjust the different properties of the navigation container. In our case, we have opted for the header to not be shown on screen. -
Step 4: Header Component
Now we will be learning how to add a simple header to our Index page. Save the image below as header.jpg and add it to the assets folder.
header.jpg Open IndexPage.js and add the code below.
The code above writes the structure for the header and also styles it.
The
IndexPagecomponent returns aViewcomponent that contains anImagecomponent and aTextcomponent. The Image component uses a local image file located at "../assets/header.jpg" as its source. The styles for the Image component are defined in the styles constant object, which is created using theStyleSheet.createmethod. The styles specify the width, height, and resize mode of the image. You may notice that we are using "100%" for the width as we want the image to expand to the full width of the mobile screen. Since the physical size of the image will be different from screen to screen, in order to maintain the aspect ratio of the image, we will need to use theresizeMode: "cover"method to allow the image to maintain its aspect ratio.The Text component displays the text "Stackie's Blog" and has styles defined in the
stylesconstant object. The styles specify the font size, font weight, text alignment, color, and text shadow properties of the text. The text also has a specified position as dictated by the top and left properties. -
Step 5: New Blog Button and Container
Now, let's create the button that we can use to create a new blog entry. We will use a component called
<TouchableOpacity>. In React Native, this component allows us as developers to create custom buttons that will show feedback when clicked.In line 1 of IndexPage.js, add “TouchableOpacity” behind the Text component in the import statement. It should look like the code below.
import { View, Image, StyleSheet, Text, TouchableOpacity } from "react-native";Bear in mind that for any component that you use, you will need to import them first. As a good practice, for any dependencies you need for a project, you should place the import statement at the top of your code.
After line 1, add the import statement below. This statement adds FontAwesome5 icons to our project.
Next, after line 11 of the
<Text>component, we will create a new<View>component that will hold the previews of our blogs and the button to create a new blog entry. Add the following code to after line 11 of IndexPage.js.The code above has a
<View>component with styles defined in thestylesobject. The styles specify the layout and appearance of the container.The button is created using a
<TouchableOpacity>component, which is a touchable component that provides visual feedback when pressed. The styles for the button are defined in thestylesobject, and they specify the appearance of the button. TheonPressprop specifies the action to be taken when the button is pressed. In this case, it navigates to theBlogPageroute in the navigation stack.The button also contains a
<FontAwesome5>component, which displays an icon, and a<Text>component, which displays the text "New Blog Entry". The<name>prop specifies the name of the icon to display. Thesizeprop specifies the size of the icon, and thecolorprop specifies the color of the icon. The styles for the text are defined in the styles object, and they specify the appearance of the text.Now, we will move on to the styling of the button and the container. Add this code after line 45 of IndexPage.js.
For this code, we will use flex to make the display flexible. Using
flexDirection:"row", we can position the components in the View element as a row. We can also align them by using thealignItemsandjustifyContentproperties.To check if you edited IndexPage.js correctly, you can check your code against the image below.
-
Step 6: BlogPage.js Setup
Similar to what we did earlier for IndexPage, we will need to create a reference to the BlogPage.js file. In App.js, we will need to import the BlogPage.js file and add the <Stack.Screen> component within the <Stack.Navigator> components.
In your App.js file, add the following two lines of code after lines 3 and line 11 respectively.
Your code below should look like this.
-
Step 7: BlogPage.js
We will now code the BlogPage.js file. This file will contain the main logic of creating, viewing, editing and deleting content. In the industry, this is also known as Create, Read, Update and Delete (CRUD).
Now add this set of import statements to BlogPage.js.
Notice that we will be using
AsyncStorageto get data from the device’s local storage. Now, we will create a functional component calledBlogPage. Add the code below after the set of import statements.The code above shows the most basic structure of a component in React and React Native. Do take note that in any programming language, when writing a function, any code that comes after the return statement will not be processed. As such, in JavaScript, we will write any states, logics or functions before the
return()statement.In between the function declaration and the return statement, or after line 6, add the code below.
To check if you have added the code correctly, you may check the image below.
The code above sets up various states that will make up how we store the data temporarily before saving it locally. Think of states as variables. In the first line of the code snippet above, we are destructuring
blog. Destructuring is when you are trying to assign a value of a variable which happens to be the key of an object. Below is the code sample of what destructuring is.let wallet = { color: “white”, value: 10.50 } let { color } = wallet // the value of “color” will be white, since it is also a property of walletWhenever we pass data from one object to another, we can always access the data transferred via the
route.params. We are checking if the previous page, IndexPage.js, has passed any selected blog to this page. If so,blogwill be populated with the data passed from the previous screen, else, blog will just be an empty object {}.In the next 4 states you see after it, we will create those states and use a condition statement to initialise the initial value of our state. Any value within the round brackets of
useStatewill be stored as the state's initial value when the page first loads.For example, when creating a counter application, a counter state will be created using the code below. Notice that the “0” is placed within useState. This is because we want to first set the value of the counter, our state, to start from 0. counter is a read-only variable. It is only allowed to be used in logical calculation and it can be displayed on screen, but to change the value, we will need to use the
setCounterfunction to change the value of state.const [counter, setCounter] = useState(0)With this in mind, for our line 9,
contentis the read-only variable state andsetContent()is the corresponding function that will be able to change the value of content. However, you may also notice this syntax being used in the useState() method. In the later part of line 9,blog? blog.content : ''checks if the previous screen passed on any blog content to the BlogPage.js file to display. This statement is the shorthand version of an if-else statement.Ultimately, we are creating a code that checks if the blog object is empty. If it is empty, we will set the initial value of content to an empty string. However, if the IndexPage.js page has passed on blog data, we will set the content to the content property of blog. This is likewise for the other states.
-
Step 8: CUD Operations
We will now move on to creating 3 crucial functions. They are
editBlog,deleteBlogand createBlog. Now, add the code shown below after line 11.Creating a Blog
To create a blog, we will create an object for each blog that the user has written. We will store all of the blogs in an array and save the array to our local storage (line 33). We will first format our blog to store the relevant content such as the title and the content. Apart from that, we will also need to create and assign a unique ID to our blog (line 30). For this, we will get the local time and convert the time to epoch time which will be a large number. Epoch is the number of seconds that have passed since 1st January 1970, midnight.
Assuming that the user will only be able to create a blog with at least 1 second between each blog creation, we can safely assume that the ID is unique. After we have set up our blog schema, we will fetch the existing blogs from the local storage. In line 25, notice the || character, which means a check will be performed for any blogs stored locally for the very first time. If there are no blogs stored, we will initialise an empty array. Using the
push()method, we will be able to add to the blogs and store them locally usingAsyncStorage.setItem()in line 53.Editing a Blog
The code provided here shows how to edit a blog in the same fashion as the creation of a blog. The difference is instead of pushing new data into the
blogsarray, we will update the data by first finding the blog index using thefindIndexmethod. In this method, we will compare the id of the blog in the array to the id of the blog that we want to edit. If they are the same, we will update the corresponding blog data. After updating the blog data, we will store the blogs in the local storage by converting them into a string usingJSON.stringify.Deleting a Blog
Similarly to the editing process, the code for deleting a blog first fetches the existing blogs from the local storage. After that, it finds the index of the blog that we want to delete. The
splicemethod is used to remove an element from an array. After removing the desired blog, we will store the updated blogs in the local storage by converting them into a string using JSON.stringify. -
Step 9: BlogPage.js Structure and Styling
In line 75, replace return() with the code below.
In the code above, you may notice that we will only show the “Delete” button (line 94) when the blog has been created. We will be able to determine it by using the
pageStatestate. From there, we will show and hide the button based on the conditional statement.In line 2, add "StatusBar'' after "Alert," as we need to import it to ensure that our blog page has a top margin of the height of the status bar (line 77). Your line 2 should now look like this.
import { View, StyleSheet, Text, TouchableOpacity, SafeAreaView, TextInput, Alert, StatusBar } from "react-native";Last but not the least, let's add the styling after the BlogPage functional component at line 127.
Now, check your code against the image below to ensure you added the code correctly.
-
Step 10: Final Touches
Lastly, in the IndexPage.js file, we will need to fetch the data stored in the local storage and display them on screen. We will display each blog entry as a row and whenever the user clicks the row, we will pass the row data to BlogPage.js.
Open IndexPage.js and add these import statements after the other import statements at the top of the file.
Then, add this code before the return statement (line 7) in the IndexPage function.
We will create a state to store all of the data fetched from the local storage. In line 7, we will initialise the initial value of
blogDatato an empty array. Next, in line 9, we will create a function that will get the blogs from ourAsyncStorage.useEffect is a hook that comes built in with React and React Native. It is a hook that will run the code given each time the page has been loaded. For this case, we will call the function,
getBlogseach time the page is opened. Once getBlogs has fetched the blogs, it will use thesetBlogData()function to store the data into the state.Add this code below the <TouchableOpacity> component, after line 37.
This code displays a list of blogs by mapping over the
blogDataarray and displaying each blog in a<TouchableOpacity>component. Each component has a unique key that is assigned to it by the blog's ID. The title and the content of the blog are displayed asTextcomponents within the <TouchableOpacity> component. The <TouchableOpacity> component is designed to be interactive. It listens for a press event and when triggered, navigates the user to theBlogPagescreen and passes theblogdata as a parameter. This allows the user to view and edit the blog details in the BlogPage screen. The component is placed inside a<ScrollView>component, which enables the user to scroll down to view all of the blogs.With the addition of the <ScrollView> component, we will also need to import it from React Native. In line 1, after TouchableOpacity and before '}', add ScrollView.
To check that you have correctly added everything correctly in this step, you may check your code against the image below.
-
Step 11: Check Your Work
Congratulations, you have just created your blog app. Now, time to test it out on your phone. Try and create a blog entry and experience making edits or deleting it afterwards.
If there are any errors and you think it could be due to a mistake in your code, you can also take reference from the files in this GitHub repository.
Find articles to support you through your journey or chat with our support team.
Help Center